FID 的技術內容事實上和我們常見的程式理論或 Design pattern 一樣,都是同一件事,差別是我更喜歡把問題放在前面,把理論放在後面,這樣才能更好的理解問題的本質。
而抽象的過程,就是把問題的本質抽離出來,讓我們能夠更好的理解問題,進而解決問題,抽到最後剩下的,就是「主線」,其餘的都是「支線」。
我們來舉例,如果我們要設計一個漢堡系統。
那麼我們可以來設計一個產生漢堡的機制,以及一個點餐的機制。
// 定义汉堡原料
const ingredients = {
bun: ["Plain Bun", "Whole Wheat Bun", "Sesame Bun"],
patty: ["Beef Patty", "Chicken Patty", "Vegetable Patty"],
toppings: ["Lettuce", "Tomato", "Onion", "Cheese", "Pickles"],
sauces: ["Ketchup", "Mustard", "Mayonnaise", "BBQ Sauce"],
};
// 随机选择原料
function getRandomIngredient(type) {
const ingredientList = ingredients[type];
const randomIndex = Math.floor(Math.random() * ingredientList.length);
return ingredientList[randomIndex];
}
// 製造漢堡 🍔
function createBurger() {
const burger = {
bun: getRandomIngredient("bun"),
patty: getRandomIngredient("patty"),
toppings: [],
sauces: [],
};
for (let i = 0; i < 3; i++) {
burger.toppings.push(getRandomIngredient("toppings"));
burger.sauces.push(getRandomIngredient("sauces"));
}
return burger;
}
// 点餐
function orderBurger() {
const burger = createBurger();
console.log("您的汉堡订单:");
console.log("面包:" + burger.bun);
console.log("肉饼:" + burger.patty);
console.log("配料:" + burger.toppings.join(", "));
console.log("酱料:" + burger.sauces.join(", "));
}
// 來點餐吧!
orderBurger();
對啊,漢堡怎麼可能是隨機的,我們點餐的時候,不是要點什麼就點什麼嗎?所以我們必須要有個 menu,於是我們又設計了一個 menu。
// 我們的菜單
const menu = [
{
name: "Classic Burger",
bun: "Plain Bun",
patty: "Beef Patty",
toppings: ["Lettuce", "Tomato", "Onion", "Cheese", "Pickles"],
sauces: ["Ketchup", "Mustard"],
},
{
name: "Chicken Burger",
bun: "Whole Wheat Bun",
patty: "Chicken Patty",
toppings: ["Lettuce", "Tomato", "Onion", "Cheese"],
sauces: ["Mayonnaise", "Mustard"],
},
{
name: "Veggie Burger",
bun: "Sesame Bun",
patty: "Vegetable Patty",
toppings: ["Lettuce", "Tomato", "Onion", "Cheese", "Pickles"],
sauces: ["Ketchup", "Mayonnaise"],
},
];
// 点餐
function orderBurger(x) {
const burger = menu(x);
console.log("您的汉堡订单:");
console.log("名称:" + burger.name);
}
// 示例点餐
orderBurger(2);
我們能點什麼餐是依賴於 menu,但是 menu 是寫死的,如果我們要新增一個漢堡,那麼我們就必須要修改 menu,這樣的話,我們的程式就不夠彈性,所以我們必須要有個機制,讓我們可以動態的新增漢堡,於是我們又設計了一個機制。
\\ 忽略
const menu = []
const choose = 0
const orderBurger = () => {}
orderByStep(
() => lookup(menu),
(menu) => menu[choose],
(burger) => orderBurger(burger)
);
我們設計了一個 orderByStep
的機制,這樣一來流程就是流程,資料就是資料,我們就可以把流程和資料分開,這樣一來,如果我們在選漢堡的和點餐的時候,有其他的邏輯,我們就可以把邏輯放在 orderByStep
裡面,而不是放在 orderBurger
裡面,這樣一來,我們就可以把 orderBurger
當成一個純函數,這樣一來,我們就可以更好的測試 orderBurger
,這樣一來,我們就可以更好的維護 orderBurger
。
\\ 忽略
const menu = []
const choose = 0
const orderBurger = () => {}
orderByStep(
() => lookup(menu),
(menu) => menu[choose],
(burger) => orderBurger(burger),
(buger) => pack(burger)
);
再次強調這裡只是一個例子,不要照抄,我們的目的是要理解 FID 的本質,而不是要學習 FID 的實作。
昨天的發文亂了,感謝網友留言提醒。
由此可見,主流程本質就是「製作」漢堡,而這個事實沒有一定的定義,所有剩下的步驟,都可以是主流程,而每個任意移動的步驟,都可以是一個副流程,我們可以任意新增「支線」來複雜化這個流程,那都是可以的。
而我們在寫程式的時候,就必須要換一個思考模式,去想程式的「執行」如何能如同一個機器般的運作,而不是按照SPEC的文字去編寫。
文中有重複的區塊,從 FID 的技術內容事實上和我們常見的程式理論或 Design pattern 一樣
這一段開始